/*
 * ringbuffer.h
 *
 *  Created on: 2021年6月6日
 *      Author: wangbing
 *      Email : mz8023yt@163.com
 */

#ifdef __cplusplus
extern "C"
{
#endif

#ifndef _RINGBUFFER_H_
#define _RINGBUFFER_H_

#include <stdint.h>
#include <stdbool.h>
#include <pthread.h>
#include "ringbuffer_config.h"

/**
 * @brief 组件版本号
 */
#define RINGBUFFER_MAIN_VER     1
#define RINGBUFFER_SUB_VER      0
#define RINGBUFFER_REV_VER      0

/**
 * @brief 返回值
 */
#define ERR                     -1
#define EINVAL                  -2
#define ENOSPC                  -3
#define ENODAT                  -4
#define ECOVER                  -5
#define ENOTINIT                -6
#define EREINIT                 -7
#define ERANGE                  -8

/**
 * @brief 宏定义
 */
#define _RINGBUFFER_IDLE_LEN_(r, w, size)           (w >= r) ? (size + r - w - 1)                       : (r - w - 1)
#define _RINGBUFFER_FILL_LEN_(r, w, size)           (w >= r) ? (w - r)                                  : (size + w - r)
#define _RINGBUFFER_BEHIND_IDLE_LEN_(r, w, size)    (w >= r) ? (r == 0) ? (size - w - 1) : (size - w)   : (r - w - 1)
#define _RINGBUFFER_BEHIND_FILL_LEN_(r, w, size)    (w >= r) ? (w - r)                                  : (size - r)

#define RINGBUFFER_IDLE_LEN(q)                      _RINGBUFFER_IDLE_LEN_(q->r, q->w, q->size)
#define RINGBUFFER_FILL_LEN(q)                      _RINGBUFFER_FILL_LEN_(q->r, q->w, q->size)
#define RINGBUFFER_BEHIND_IDLE_LEN(q)               _RINGBUFFER_BEHIND_IDLE_LEN_(q->r, q->w, q->size)
#define RINGBUFFER_BEHIND_FILL_LEN(q)               _RINGBUFFER_BEHIND_FILL_LEN_(q->r, q->w, q->size)

#define RINGBUFFER_UPDATE(rw, step, size)           ((rw + step) >= size) ? (rw + step - size) : (rw + step)

/**
 * @brief 队列
 */
typedef struct _RINGBUFFER_
{
    uint8_t *addr;                          // 环形队列首地址
    uint32_t size;                          // 环形队列大小
    uint32_t r;                             // 读指针偏移
    uint32_t w;                             // 写指针偏移
    uint32_t init;                          // 是否初始化标记
    pthread_mutex_t lock;                   // 互斥锁
} RINGBUFFER;

/**
 * @brief API接口
 */
int ringbuffer_init(RINGBUFFER *rbuf, uint32_t size);
int ringbuffer_deinit(RINGBUFFER *rbuf);

int ringbuffer_read(RINGBUFFER *rbuf, uint8_t *obuf, uint32_t olen);
int ringbuffer_write(RINGBUFFER *rbuf, uint8_t *ibuf, uint32_t ilen);
int ringbuffer_write_with_header(RINGBUFFER *rbuf, uint8_t *hd_buf, uint32_t hd_len, uint8_t *ibuf, uint32_t ilen);

bool ringbuffer_is_empty(RINGBUFFER *rbuf);
bool ringbuffer_is_full(RINGBUFFER *rbuf);
uint32_t ringbuffer_idle_length_get(RINGBUFFER *rbuf);
uint32_t ringbuffer_fill_length_get(RINGBUFFER *rbuf);

int ringbuffer_lock(RINGBUFFER *rbuf);
int ringbuffer_trylock(RINGBUFFER *rbuf);
int ringbuffer_unlock(RINGBUFFER *rbuf);

int ringbuffer_clean(RINGBUFFER *rbuf);
int ringbuffer_print(RINGBUFFER *rbuf);
int ringbuffer_status(RINGBUFFER *rbuf);
int ringbuffer_dump(RINGBUFFER *rbuf);

#endif /* _RINGBUFFER_H_ */

#ifdef __cplusplus
}
#endif

